#ifndef _TEST_FUNC
#define _TEST_FUNC

#include "GPTool.h"

namespace DataTest
{
	void DataTest(void);
}

namespace TestOsVersion
{
	void TestOsVersion(void);
}

namespace TestMacroClass
{
	void TestMacroClass(void);
}

namespace TestMemcpy
{
#define TINY_BLOCK_COPY 64       // upper limit for movsd type copy
	// The smallest copy uses the X86 "movsd" instruction, in an optimized
	// form which is an "unrolled loop".

#define IN_CACHE_COPY 64 * 1024  // upper limit for movq/movq copy w/SW prefetch
	// Next is a copy that uses the MMX registers to copy 8 bytes at a time,
	// also using the "unrolled loop" optimization.   This code uses
	// the software prefetch instruction to get the data into the cache.

#define UNCACHED_COPY 197 * 1024 // upper limit for movq/movntq w/SW prefetch
	// For larger blocks, which will spill beyond the cache, it's faster to
	// use the Streaming Store instruction MOVNTQ.   This write instruction
	// bypasses the cache and writes straight to main memory.  This code also
	// uses the software prefetch instruction to pre-read the data.
	// USE 64 * 1024 FOR THIS VALUE IF YOU'RE ALWAYS FILLING A "CLEAN CACHE"

#define BLOCK_PREFETCH_COPY  infinity // no limit for movq/movntq w/block prefetch 
#define CACHEBLOCK 80h // number of 64-byte blocks (cache lines) for block prefetch
	// For the largest size blocks, a special technique called Block Prefetch
	// can be used to accelerate the read operations.   Block Prefetch reads
	// one address per cache line, for a series of cache lines, in a short loop.
	// This is faster than using software prefetch.  The technique is great for
	// getting maximum read bandwidth, especially in DDR memory systems.
	inline void appMemcpy(void* pkDst,const void* pkSrc,int iCount);

	void TestMemCpy(void);
}

namespace TestBind
{
	namespace
	{
		class placeholders{};
		placeholders _1;
	}

	template<typename R,typename T,typename Arg>
	class simple_bind_t
	{
		typedef R (T::*fn)(Arg);
		fn fn_;
		T t_;
		 
	public:
		simple_bind_t(fn f,const T& t):fn_(f),t_(t){}
		R operator()(Arg& a)
		{
			return (t_.*fn_)(a);
		}
	};

	template<typename R,typename T,typename Arg>
	simple_bind_t<R,T,Arg> simple_bind(R (T::*fn)(Arg),const T& t,const placeholders&)
	{
		return simple_bind_t<R,T,Arg>(fn,t);
	}

	class Test
	{
	public:
		void do_stuff(const std::vector<int>& v)
		{
			std::copy(v.begin(),v.end(),std::ostream_iterator<int>(std::cout,"\n"));
		}
	};

	void TestMain();
}

namespace TestTemplateLink
{
	struct PeopleLink
	{
		PeopleLink()
		{
			pkPrev = NULL;
			pkNext = NULL;
			iAge = 0;
			iSex = 0;
		}

		PeopleLink* pkPrev;
		PeopleLink* pkNext;

		int			iAge;
		std::string kName;
		int			iSex;
	};

	class TestPeopleLink
	{
	public:
		TestPeopleLink();
		~TestPeopleLink();

		void TestLink();
	private:
		PeopleLink* pkFirst;
		PeopleLink* pkLast;
		int			iLinkNums;

		std::vector<PeopleLink*> m_pkVLink;
	};
}

namespace MaxCommonDivisor
{
	int GetMaxCommonDivisor(int iNum1,int iNum2);
	int gcd(int i1,int i2);
	void MaxTest();
}

namespace TestSTLAndMAPIterator
{
	void Test();
}

#endif
